﻿using System;
using Nofs.Net.Common.Interfaces.Library;
using biz.ritter.javapi.net;
using biz.ritter.javapi.util;
using biz.ritter.javapi.lang;


namespace Nofs.Net.nofs.netfs
{

    //@DomainObject
    //@FolderObject(CanAdd=false, CanRemove=false)
    public class TCPConnection
    {
        public TCPConnection() { }

        private String _name;
        //@ProvidesName
        public void setName(String name) { _name = name; }
        //@ProvidesName
        public String getName() { return _name; }

        private IDomainObjectContainerManager _containerManager;

        //@NeedsContainerManager
        public void setContainerManager(IDomainObjectContainerManager manager)
        {
            _containerManager = manager;
        }

        private Socket _socket;
        private ErrorLog _errorLog;

        //@SuppressWarnings("unchecked")
        private ErrorLog getErrorLog()// throws Exception 
        {
            if (_errorLog == null)
            {
                IDomainObjectContainer<ErrorLog> logContainer = (IDomainObjectContainer<ErrorLog>)_containerManager.GetContainer(typeof(ErrorLog).getClass());
                _errorLog = logContainer.NewPersistentInstance();
            }
            return _errorLog;
        }

        //@SuppressWarnings("unchecked")
        private void LogError(String errorMessage) //throws Exception 
        {
            getErrorLog().getErrorMessages().add(errorMessage);
            _containerManager.GetContainer(typeof(ErrorLog).getClass()).ObjectChanged(getErrorLog());
        }

        //@FolderObject(CanAdd=false, CanRemove=false)
        public List<ErrorLog> getLog() //throws Exception 
        {
            List<ErrorLog> errorLogs = new LinkedList<ErrorLog>();
            errorLogs.add(getErrorLog());
            return errorLogs;
        }

        private LinkedList<Packet> _sendQueue = new LinkedList<Packet>();
        //@FolderObject(CanAdd=true, CanRemove=false)
        public List<Packet> getSendQueue() //throws Exception 
        {
            return _sendQueue;
        }

        private LinkedList<Packet> _receiveQueue = new LinkedList<Packet>();
        //@FolderObject(CanAdd=false, CanRemove=true)
        public LinkedList<Packet> getRecvQueue()// throws Exception 
        {
            return _receiveQueue;
        }

        //@Executable
        public void Recv(String size, String packetName) //throws Exception 
        {
            byte[] data = new byte[Integer.parseInt(size)];
            int offset = 0;
            while (offset < data.Length)
            {
                offset += _socket.getInputStream().read(data, offset, data.Length - offset);
            }
            Packet packet = new Packet();
            packet.setName(packetName);
            packet.setData(data);
            _receiveQueue.add(packet);
        }

        //@Executable
        public void Send(String packetName) //throws Exception 
        {
            Packet packetToSend = null;
            foreach (Packet packet in _sendQueue)
            {
                if (packet.getName() == packetName)
                {
                    packetToSend = packet;
                    break;
                }
            }
            if (packetToSend != null)
            {
                _socket.getOutputStream().write(packetToSend.getData());
                _sendQueue.remove(packetToSend);
            }
        }

        //@Executable
        public void ConnectTo(String host, String port)// throws Exception 
        {
            try
            {
                _socket = new Socket(host, Integer.parseInt(port));
            }
            catch (System.Exception e)
            {
                LogError(e.getMessage());
            }
        }

        //@Executable
        public void Close()// throws Exception 
        {
            if (_socket == null)
            {
                LogError("Socket is not connected or open");
            }
            else
            {
                try
                {
                    _socket.close();
                }
                catch (System.Exception e)
                {
                    LogError(e.getMessage());
                }
            }
        }
    }

}
